package com.brillilab.service.core.inventory.impl;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.brillilab.common.constant.ResultEnum;
import com.brillilab.common.entity.PageVo;
import com.brillilab.common.exceptions.BrillilabException;
import com.brillilab.dao.mapper.inventory.ReagentInventoryMapper;
import com.brillilab.dao.mapper.system.IdUtilMapper;
import com.brillilab.domain.enums.common.BoolEnum;
import com.brillilab.domain.enums.common.IsDeleteEnum;
import com.brillilab.domain.enums.lab.LabMemberPowerEnum;
import com.brillilab.domain.enums.space.SpaceTypeEnum;
import com.brillilab.domain.enums.system.IdUtilTypeEnum;
import com.brillilab.domain.po.experiments.ExperimentStepReagent;
import com.brillilab.domain.po.inventory.ReagentInventory;
import com.brillilab.domain.po.kit.KitSpec;
import com.brillilab.domain.po.system.IdUtil;
import com.brillilab.domain.vo.inventory.ReagentInventoryWithOwner;
import com.brillilab.domain.vo.inventory.SpaceInventoryPaged;
import com.brillilab.domain.vo.kit.DeviceUnlock;
import com.brillilab.domain.vo.user.UserInfoVo;
import com.brillilab.service.core.inventory.IReagentInventoryService;
import com.github.pagehelper.PageHelper;

/**
 * @author wuzhiyu
 * @Title: ReagentInventoryServiceImpl
 * @ProjectName brill_lab
 * @Description: TODO
 * @date 2018/11/1420:10
 */
@Service
@Transactional
public class ReagentInventoryServiceImpl implements IReagentInventoryService {
    @Resource
    private ReagentInventoryMapper reagentInventoryMapper;
    @Resource
    private IdUtilMapper idUtilMapper;

    @Override
    public Integer InventoryCountInSpace(Long spaceId, SpaceTypeEnum spaceTypeEnum) {
        LambdaQueryWrapper<ReagentInventory> wrapper = new LambdaQueryWrapper<>();
        switch (spaceTypeEnum) {
            case ROOM:
                wrapper.eq(ReagentInventory::getRoomId, spaceId);
                break;
            case DEVICE:
                wrapper.eq(ReagentInventory::getDeviceId, spaceId);
                break;
            case PANEL:
                wrapper.eq(ReagentInventory::getPanelId, spaceId);
                break;
            case BOX:
                wrapper.eq(ReagentInventory::getBoxId, spaceId);
                break;
        }
        wrapper.eq(ReagentInventory::getIsDelete, IsDeleteEnum.NO);
        return reagentInventoryMapper.selectCount(wrapper);
    }

    @Override
    public List<ReagentInventory> getBoxInventoryList(Long boxId) {
        LambdaQueryWrapper<ReagentInventory> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ReagentInventory::getBoxId, boxId);
        wrapper.eq(ReagentInventory::getIsDelete, IsDeleteEnum.NO.getValue());
        return reagentInventoryMapper.selectList(wrapper);
    }

    @Override
    public List<ReagentInventory> selectListByKitId(Long kitId) {
        LambdaQueryWrapper<ReagentInventory> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ReagentInventory::getKitId, kitId);
        wrapper.eq(ReagentInventory::getIsDelete, IsDeleteEnum.NO);
        return reagentInventoryMapper.selectList(wrapper);
    }

    @Override
    public List<ReagentInventory> getInventoryList(Long kitId, Long labMemberId, Long groupId) {
        if (kitId == null && groupId == null) {
            throw new BrillilabException(ResultEnum.REQUEST_PARAM_LACK);
        }
        LambdaQueryWrapper<ReagentInventory> wrapper = new LambdaQueryWrapper<>();
        if (kitId != null) {
            wrapper.eq(ReagentInventory::getKitId, kitId);
        }
        wrapper.eq(ReagentInventory::getIsDelete, IsDeleteEnum.NO.getValue());
        if (labMemberId != null) {
            wrapper.and(rap -> rap.isNull(ReagentInventory::getLabMemberId).or().eq(ReagentInventory::getLabMemberId, labMemberId));
        }
        if (groupId != null) {
            wrapper.eq(ReagentInventory::getGroupId, groupId);
        }
        return reagentInventoryMapper.selectList(wrapper);
    }

    @Override
    public Long generateInventoryGroupId() {
        IdUtil id = new IdUtil();
        id.setName(IdUtilTypeEnum.INVENTORY_GROUP.getType());
        idUtilMapper.insert(id);
        return id.getId();
    }

    @Override
    public Long generateInventoryCombId() {
        IdUtil id = new IdUtil();
        id.setName(IdUtilTypeEnum.POS_COMB_ID.getType());
        idUtilMapper.insert(id);
        return id.getId();
    }

    @Override
    public Integer saveInventoryList(List<ReagentInventory> list) {
        return reagentInventoryMapper.saveInventoryList(list);
    }

    @Override
    public Integer changBoxInventory(ReagentInventory newInventory) {
        return reagentInventoryMapper.changBoxInventory(newInventory);
    }

    @Override
    public List<ReagentInventory> listByKitBoxId(Long kitBoxId) {
        LambdaQueryWrapper<ReagentInventory> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ReagentInventory::getKitBoxId, kitBoxId);
        return reagentInventoryMapper.selectList(wrapper);
    }

    @Override
    public Integer updateListInventoryPosition(List<ReagentInventory> updateList) {
        return reagentInventoryMapper.updateListInventoryPosition(updateList);
    }

    @Override
    public PageVo<ReagentInventoryWithOwner> getSpaceInventoryPaged(Long labId, SpaceInventoryPaged search) {
        PageHelper.startPage(search.getPageNum(), search.getPageSize());
        List<ReagentInventoryWithOwner> reagentInventoryList = reagentInventoryMapper.getSpaceInventoryPaged(labId, search);
        PageVo<ReagentInventoryWithOwner> vo = new PageVo<ReagentInventoryWithOwner>(reagentInventoryList);
        return new PageVo<ReagentInventoryWithOwner>(vo.getPageNum(), vo.getPageSize(), vo.getTotalRow(), reagentInventoryList);
    }

    @Override
    public boolean deleteById(Long id) {
        ReagentInventory inventory = this.selectById(id);
        inventory.setIsDelete(IsDeleteEnum.YES.getValue());
        return this.updateById(inventory);
    }

    @Override
    public ReagentInventory selectById(Long id) {
        return reagentInventoryMapper.selectById(id);
    }

    @Override
    public boolean updateById(ReagentInventory entity) {
        Integer b = reagentInventoryMapper.updateById(entity);
        return b == 1 ? true : false;
    }

    @Override
    public Integer updateInventoryListAmount(List<ReagentInventory> list) {
        return reagentInventoryMapper.updateInventoryListAmount(list);
    }

    @Override
    public List<ReagentInventory> getInventoryCountByKitSpec(List<KitSpec> specLIst) {
        return reagentInventoryMapper.getInventoryCountByKitSpec(specLIst.get(0).getKitId(), specLIst.get(0).getKitSize());
    }

    @Override
    public Integer deleteInventoryByKitSpec(List<KitSpec> specList) {
        return reagentInventoryMapper.deleteInventoryByKitSpec(specList.get(0).getKitId(), specList.get(0).getKitSize());
    }

    @Override
    public List<ReagentInventory> getSampleGroupInventoryList(Long sampleGroupId, Long labMemberId) {
        return reagentInventoryMapper.getSampleGroupInventoryList(sampleGroupId, labMemberId);
    }

    @Override
    public Integer deleteBatch(List<Long> deleteIds) {
        if(deleteIds.size()>0){
            return reagentInventoryMapper.deleteBatch(deleteIds);
        }
        return 0;
    }

    @Override
    public List<ReagentInventory> selectByReagentIdList(List<Long> reagentIds,List<Long> groupIds) {
        List<ReagentInventory> inventories=null;
        if(reagentIds!=null && reagentIds.size()>0){

            LambdaQueryWrapper<ReagentInventory> wrapper=new LambdaQueryWrapper<>();
            wrapper.in(ReagentInventory::getReagentId,reagentIds);
            if(groupIds != null && groupIds.size() > 0){
                wrapper.in(ReagentInventory::getGroupId,groupIds);
            }
            wrapper.eq(ReagentInventory::getIsDelete,IsDeleteEnum.NO.getValue());
            inventories=reagentInventoryMapper.selectList(wrapper);
        }
        return inventories!=null ? inventories : new ArrayList<>(0);
    }

    @Override
    public boolean updateRoomName(Long roomId, String name) {
        ReagentInventory inv = new ReagentInventory();
        inv.setRoomId(roomId);
        inv.setRoomName(name);
        LambdaQueryWrapper<ReagentInventory> query = new LambdaQueryWrapper<>();
        query.eq(ReagentInventory::getRoomId, roomId);
        reagentInventoryMapper.update(inv, query);
        return true;
    }

    @Override
    public List<ReagentInventory> getInventoryListByKitBoxId(Long kitBoxId) {
        LambdaQueryWrapper<ReagentInventory> query = new LambdaQueryWrapper<>();
        query.eq(ReagentInventory::getKitBoxId, kitBoxId);
        query.eq(ReagentInventory::getIsDelete, IsDeleteEnum.NO.getValue());
        return reagentInventoryMapper.selectList(query);
    }

    @Override
    public List<ReagentInventory> selectList(List<Long> inventoryIds, Integer isDelete) {
        Assert.isTrue(inventoryIds != null, "参数缺失！");
        return reagentInventoryMapper.selectListByIds(inventoryIds, isDelete);
    }

    @Override
    public Integer deleteByKitId(Long kitId) {
        LambdaQueryWrapper<ReagentInventory> query = new LambdaQueryWrapper<>();
        query.eq(ReagentInventory::getKitId, kitId);
        ReagentInventory inv = new ReagentInventory();
        inv.setIsDelete(IsDeleteEnum.YES.getValue());
        return reagentInventoryMapper.update(inv, query);
    }

    @Override
    public Integer getBoxGridInventoryCount(Long boxGridId) {
        LambdaQueryWrapper<ReagentInventory> query = new LambdaQueryWrapper<>();
        query.eq(ReagentInventory::getIsDelete, IsDeleteEnum.NO.getValue());
        query.eq(ReagentInventory::getBoxGridId, boxGridId);
        return reagentInventoryMapper.selectCount(query);
    }

    @Override
    public List<ReagentInventory> listByInventoryGroupId(Long posCombId) {
        LambdaQueryWrapper<ReagentInventory> query = new LambdaQueryWrapper<>();
        query.eq(ReagentInventory::getPosCombId, posCombId);
        query.eq(ReagentInventory::getIsDelete, BoolEnum.FALSE.getValue());
        return reagentInventoryMapper.selectList(query);
    }

    @Override
    public boolean changMoveBoxInventory(ReagentInventory newInv) {
        return reagentInventoryMapper.changMoveBoxInventory(newInv)>0;
    }

    @Override
    public List<ReagentInventory> selectListByReagentId(Long reagentId) {
        return reagentInventoryMapper.selectList(new LambdaQueryWrapper<ReagentInventory>()
                .eq(ReagentInventory::getReagentId,reagentId)
                .eq(ReagentInventory::getIsDelete,BoolEnum.FALSE.getValue()));
    }

    @Override
    public List<DeviceUnlock> selectKitUsageDeviceUnLockList(List<Long> inventoryIds) {
        return reagentInventoryMapper.selectKitUsageDeviceUnLockList(inventoryIds);
    }

    @Override
    public List<ReagentInventory> selectListByReagentIds(List<Long> reagentIds) {
        if(reagentIds!=null && reagentIds.size()>0){
            return reagentInventoryMapper.selectList(
                    new LambdaQueryWrapper<ReagentInventory>()
                            .in(ReagentInventory::getReagentId,reagentIds)
                            .eq(ReagentInventory::getIsDelete,BoolEnum.FALSE.getValue()));
        }
        return new ArrayList<>(0);
    }

    @Override
    public List<ReagentInventory> selectByStepReagents(List<ExperimentStepReagent> stepReagents) {
        return reagentInventoryMapper.selectByStepReagents(stepReagents);
    }

	@Override
	public boolean isUseInventory(UserInfoVo user, Long kitId) {
		 LambdaQueryWrapper<ReagentInventory> wrapper = new LambdaQueryWrapper<>();
	     wrapper.eq(ReagentInventory::getKitId, kitId);
	     wrapper.eq(ReagentInventory::getIsDelete, IsDeleteEnum.NO);
	     if(!user.getIsOwner() && ( CollectionUtils.isEmpty(user.getPowers())  
	    		 || !user.getPowers().stream().anyMatch(p -> p.getPower().equals(LabMemberPowerEnum.reagent)))) {
	    	 wrapper.and(rap -> rap.isNull(ReagentInventory::getLabMemberId).or().eq(ReagentInventory::getLabMemberId, user.getLabMemberId()));
	     }
	    Integer count = reagentInventoryMapper.selectCount(wrapper);
		return count > 0;
	}

    @Override
    public List<ReagentInventory> selectListByKitIdList(List<Long> kitIds,List<Long> groupIds) {
        List<ReagentInventory> inventories=null;
        if(kitIds!=null && kitIds.size()>0){

            LambdaQueryWrapper<ReagentInventory> wrapper=new LambdaQueryWrapper<>();
            wrapper.in(ReagentInventory::getKitId,kitIds);
            if(groupIds != null && groupIds.size() > 0){
                wrapper.in(ReagentInventory::getGroupId,groupIds);
            }
            wrapper.eq(ReagentInventory::getIsDelete,IsDeleteEnum.NO.getValue());
            inventories=reagentInventoryMapper.selectList(wrapper);
        }
        return inventories!=null ? inventories : new ArrayList<>(0);
    }

}
